home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Font Handler / PrinterFonts.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  29.6 KB  |  963 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        PrinterFonts.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains for the Font Handler code
  6.                         for building printer font lists.
  7.  
  8.      Version:    Technology:    Quickdraw GX 1.1.x
  9.       
  10.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  11. */
  12.  
  13. #include <Collections.h>
  14. #include <MacMemory.h>
  15. #include <String.h>
  16. #include "GXToPSBuildConfig.h"
  17. #include <GXExceptions.h>
  18. #include "IOUtilities.h"
  19. #include "GXPrintingUniverse.h"
  20.  
  21. #include "FontDatabase.h"
  22. #include "FontHandler.h"
  23. #include "FontHandlerPrivate.h"
  24. #include "FontHandlerVariations.h"
  25.  
  26. #ifdef resumeLabel
  27.     #undef resumeLabel
  28. #endif
  29. #define resumeLabel(exception)
  30.  
  31. #define    sizeField(structure, field)        sizeof( ((structure *)0)->field )
  32. #define    sizeArray(type, length)        ( (long) &((type *)0)[length] )
  33. #define offsetField(type, field)        ( (long) &((type *)0)->field )
  34.  
  35. #define    Exchange(a, b)                { register long temp = (a); (a) = (b); (b) = temp; }
  36. #define SwapType(type, a, b)        { register type temp = (a); (a) = (b); (b) = temp; }
  37.  
  38.  
  39. //<FF>
  40. /********************************************
  41.  
  42.     Function:  FHMarkSEACPositions
  43.     
  44.     Function marks the positions in the encoding
  45.     with the 0xFFFE sentinal value that says
  46.     leave for SEAC encoding.  Having this value
  47.     in there will prevent me from using it as an
  48.     encoding position for a downloaded font.
  49.     
  50.     mark:        Boolean, true to initially mark to
  51.                             avoid using
  52.                         false to unmark so encoding is valid.
  53.     
  54. *********************************************/
  55. void FHMarkSEACPositions(gxFont theFont, unsigned short *encoding, Boolean mark );
  56. void FHMarkSEACPositions(gxFont theFont, unsigned short *encoding, Boolean mark )
  57.     {
  58.         long                                index;
  59.         gxFontFormatTag            fontFormat;
  60.         
  61.         unsigned short SEAC_CODES [] = {
  62.         
  63.             /* STD_A */  0x41,
  64.             /* STD_C */  0x43,
  65.             /* STD_E */  0x45,
  66.             /* STD_I */  0x49,
  67.             /* STD_N */  0x4E,
  68.             /* STD_O */  0x4F,
  69.             /* STD_S */  0x53,
  70.             /* STD_U */  0x55,
  71.             /* STD_Y */  0x59,
  72.             /* STD_Z */  0x5A,
  73.             
  74.             /* STD_a */  0x61,
  75.             /* STD_c */  0x63,
  76.             /* STD_e */  0x65,
  77.             /* STD_i */  0x69,
  78.             /* STD_n */  0x6E,
  79.             /* STD_o */  0x6F,
  80.             /* STD_s */  0x73,
  81.             /* STD_u */  0x75,
  82.             /* STY_y */  0x79,
  83.             /* STD_z */  0x7A,
  84.             
  85.             /* STD_acute */             0xC2,
  86.             /* STD_caron */             0xCF,
  87.             /* STD_cedilla */            0xCB,
  88.             /* STD_circumflex */    0xC3,
  89.             /* STD_dieresis */        0xC8,
  90.             /* STD_grave */             0xC1,
  91.             /* STD_ring */                0xCA,
  92.             /* STD_tilde */              0xC4,
  93.             /* STD_dotlessi */        0xF5
  94.         
  95.         };
  96.  
  97.         fontFormat = GXGetFontFormat(theFont);
  98.         
  99.         if (fontFormat == 'typ1') {
  100.         
  101.             if (GXCountFontGlyphs(theFont) > 0x0000FFFE) {
  102.  
  103.                 #if DEBUGLEVEL > 0
  104.                 dprintf(notrace, "Can't guarantee SEAC with font that has over 65534 glyphs");
  105.                 #endif
  106.                 
  107.             } else {
  108.             
  109.                 long count = sizeof(SEAC_CODES) / sizeof(unsigned short);
  110.         
  111.                 /** Mark all of the positions in the encoding for SEAC **/
  112.                 
  113.                 for (index = 0; index < count; ++index)
  114.                     if (mark)
  115.                         encoding[ SEAC_CODES[index] ] = 0xFFFE;
  116.                     else
  117.                         encoding[ SEAC_CODES[index] ] = 0xFFFF;
  118.                                     
  119.             }//end if
  120.             
  121.         }//end if
  122.     
  123.     }//FHMarkSEACPositions
  124.  
  125.  
  126.  
  127. //<FF>
  128. /***************************************
  129.  
  130.     Function builds the glyph to character mapping for using printer resident composite fonts
  131.     
  132. ****************************************/
  133. OSErr FHMakeGlyphToCharMap(TPrinterFontRec *printerFont);
  134. OSErr FHMakeGlyphToCharMap(TPrinterFontRec *printerFont)
  135.     {
  136.         OSErr                        status = kNoPOSTtable4;
  137.         gxFont                    theFont = printerFont->theRealFont;
  138.  
  139.  
  140.         #define postscriptTableTag                0x706f7374    /* 'post' */
  141.         
  142.         long        tableindx;
  143.         long        tablesize;
  144.         
  145.         if( ( tablesize = GXFindFontTable( theFont, postscriptTableTag, nil, &tableindx ) ) && tableindx ) {
  146.  
  147.             /* the following definitions fromt the truetpe scaler file 'truetype types.h' */
  148.             
  149.             struct    postTableHeader {
  150.                 Fixed        version;
  151.                 Fixed        italicAngle;
  152.                 short        underlinePosition;
  153.                 short        underlineThickness;
  154.                 short        isFixedPitch;
  155.                 short        pad;
  156.                 unsigned long    minMemType42;
  157.                 unsigned long    maxMemType42;
  158.                 unsigned long    minMemType1;
  159.                 unsigned long    maxMemType1;
  160.         
  161.                 unsigned short data[];
  162.         
  163.             };
  164.  
  165.             long    version;
  166.             
  167.             /** The data in the post table 4 is the glyph code to character code mapping **/
  168.  
  169.             if( GXGetFontTableParts( theFont, tableindx, 0, sizeof( version ), &version, nil ) 
  170.                 && ( version == 0x40000 ) ) {
  171.                 
  172.                 Handle                      dataHdl;
  173.                 unsigned short    *dataPtr;
  174.                 long        count = GXCountFontGlyphs(theFont);
  175.                 
  176.                 // time to load in the whole table 
  177.                 
  178.                 status = PrNewHandle(&dataHdl, sizeof(unsigned short) * count );
  179.                 nrequire(status, failed_newHandle);
  180.                 
  181.                 HLock( dataHdl );
  182.                 dataPtr = * (unsigned short **) dataHdl;
  183.                         
  184.                 (void) GXGetFontTableParts( theFont, tableindx, offsetField( struct    postTableHeader, data ), 
  185.                             sizeof( unsigned short ) * count, dataPtr, nil );
  186.                         
  187.                 HUnlock( dataHdl );
  188.                 
  189.                 printerFont->glyphToCharCodeMap = dataHdl;
  190.                                 
  191.             }//end if
  192.             
  193.         
  194.         }//end if
  195.         
  196.         #undef postscriptTableTag
  197.     
  198. failed_newHandle:
  199.         return(status);
  200.         
  201.     }//FHMakeGlyphToCharMap
  202.     
  203.     
  204.     
  205. //<FF>
  206. /********************************************
  207.  
  208.     Function: FHAddGlyphHash
  209.     
  210.     Function finds an empty spot in the hash table
  211.     for a glyph code.  Adds glyph ID to hash table.
  212.  
  213.     glyphIndex:        the index to hash.
  214.     printerCodes:    the hash table array.
  215.     
  216.     Hash function is index % 256, 
  217.             simple linear probe collision resolution.
  218.  
  219.     Function returns whether or not there was room in the
  220.     table.
  221.     
  222. *********************************************/
  223. Boolean FHAddGlyphHash(long glyphIndex, unsigned short *printerCodes);
  224. Boolean FHAddGlyphHash(long glyphIndex, unsigned short *printerCodes)
  225.     {
  226.         register long                        hashValue;
  227.         register unsigned short *entry;            
  228.         Boolean                                 wrappedAround = false;
  229.         Boolean                                    hadRoom = true;
  230.         
  231.         hashValue = glyphIndex & 0x000000FF;                // index % 256.
  232.         
  233.         entry = printerCodes + hashValue;                        // Get a pointer into the table.
  234.         
  235.         if (*entry != fhSentinalGlyphCode) {                // Was there a collision?
  236.         
  237.             if (++hashValue >= 256) {            // advance to next position, do we have to wrap around?
  238.             
  239.                 hashValue = 0;
  240.                 wrappedAround = true;
  241.                 
  242.             }//end if
  243.  
  244.             entry = printerCodes + hashValue;                    // Get the pointer again.
  245.             
  246.             while (true) {                                                        //     Yes, resolve collision.
  247.     
  248.                 if (*entry != fhSentinalGlyphCode) {
  249.                 
  250.                     ++hashValue;
  251.                     ++entry;
  252.                 
  253.                     if (hashValue >= 256) {            // wrap around if necessary.
  254.                     
  255.                         if (wrappedAround) {
  256.                         
  257.                             hadRoom = false;
  258.                             break;
  259.                             
  260.                         }//end if
  261.                         
  262.                         hashValue = 0;
  263.                         entry = printerCodes;
  264.     
  265.                         wrappedAround = true;
  266.                         
  267.                     }//end if
  268.                     
  269.                 } else {
  270.                     
  271.                     break;                    // found an open entry.
  272.                     
  273.                 }//end if
  274.             
  275.             }//end while
  276.         
  277.         
  278.         }//end if
  279.         
  280.         if (hadRoom)
  281.             *entry = glyphIndex;
  282.  
  283.         return(hadRoom);
  284.     
  285.     }//FHAddGlyphHash
  286.  
  287.  
  288.  
  289. /********************************************
  290.  
  291.     Function: FHGetGlyphHash
  292.     
  293.     Function Returns printer code to use for the glyph index.
  294.  
  295.     glyphIndex:        The glyph index.
  296.     printerCodes:    the hash table array.
  297.     
  298.     Hash function is index % 256, 
  299.             simple linear probe collision resolution.
  300.     
  301. *********************************************/
  302. unsigned short FHGetGlyphHash(long glyphIndex, unsigned short *printerCodes)
  303.     {
  304.         register long                        hashValue;
  305.         register unsigned short *entry;
  306. #if DEBUGLEVEL > 1
  307.         Boolean    wrappedAround = false;
  308. #endif
  309.         
  310.         hashValue = glyphIndex & 0x000000FF;                // index % 256.
  311.         
  312.         entry = printerCodes + hashValue;                        // Get a pointer into the table.
  313.         
  314.         if (*entry != glyphIndex) {                    // First hash didn't find it?
  315.         
  316.             if (++hashValue >= 256) {                                // do we have to wrap around?
  317.             
  318.                 hashValue = 0;
  319.             
  320.                 #if DEBUGLEVEL > 1
  321.                     wrappedAround = true;
  322.                 #endif
  323.                 
  324.             }//end if
  325.             
  326.             entry = printerCodes + hashValue;                    // Get the pointer again.
  327.  
  328.             while (true) {            // try to find it.
  329.  
  330.                 if (*entry != glyphIndex) {
  331.                 
  332.                     ++hashValue;
  333.                     ++entry;
  334.                 
  335.                     if (hashValue >= 256) {            // wrap around if necessary.
  336.                                             
  337.                         #if DEBUGLEVEL > 1
  338.                             if (wrappedAround) {
  339.                                 dprintf(notrace, "Couldn't find glyph %X in hash table, fatal error", glyphIndex);
  340.                                 dprintf(notrace, "Hash table: %X", printerCodes);
  341.                                 break;
  342.                             }
  343.                         #endif
  344.  
  345.                         hashValue = 0;
  346.                         entry = printerCodes;
  347.                         #if DEBUGLEVEL > 1
  348.                             wrappedAround = true;
  349.                         #endif
  350.                                 
  351.                     }//end if
  352.                     
  353.                 } else {
  354.                 
  355.                     break;                    // found match.
  356.                     
  357.                 }//end if
  358.             
  359.             }//end while
  360.         
  361.         
  362.         }//end if
  363.         
  364.         return(hashValue);            // The index of the entry, this will be the printer code to use.
  365.     
  366.     }//FHGetGlyphHash
  367.  
  368.  
  369.  
  370. //<FF>
  371. /********************************************
  372.  
  373.     Function: FHMakePrinterGlyphEncoding
  374.     
  375.     Function makes the encoding hash tables and usage arrays
  376.     for a printer font record.  If for a downloaded font
  377.     pass nil for the fontLocation pointer.
  378.     
  379.     numGlyphs:                    Number of glyphs in the system font.
  380.     docGlyphBits:                Document glyph usage array.
  381.     printerFont:                A printer font record pointer.
  382.     fontLocation:                A printer font glyph location record.  (Pass nil for encoding downloaded font)
  383.     start:                            Starting glyph index to encode.      Last Glyph encoded returned here.
  384.                                                 Start at this glyph for next font encoding for the printer-resident fonts.
  385.     numEncoded:                    returned:  number of glyphs encoded in this font.
  386.     fdbFlags:                        font database flags for this font.
  387.     doResidentGlyphs:        pass true if making encoding for resident glyphs, false for downloaded glyphs
  388.     
  389.     returns: Boolean indicating that we tried to add glyphs into the hash table, but couldn't because
  390.                             it was full, indicating we need another printer font.  This is slightly deceptive
  391.                             parameter name in that when being called with doResidentGlyphs=true, needMoreFonts
  392.                             will return true if we needed more printer-fonts to encode all of the resident glyphs.
  393.                             in the doResidentGlyphs=false case, it returns true if we need more printer-fonts
  394.                             to encode all of the document glyphs we need to download.
  395.     
  396. *********************************************/
  397. Boolean FHMakePrinterGlyphEncoding(long numGlyphs, unsigned long *docGlyphBits,  
  398.                                                                     TPrinterFontRec *printerFont, gxPrinterGlyphsRec *fontLocation,
  399.                                                                     long *start, long *numEncoded, Boolean doResidentGlyphs,
  400.                                                                     TfdbInfoFlags fdbFlags, OSErr *status);
  401. Boolean FHMakePrinterGlyphEncoding(long numGlyphs, unsigned long *docGlyphBits,  
  402.                                                                     TPrinterFontRec *printerFont, gxPrinterGlyphsRec *fontLocation,
  403.                                                                     long *start, long *numEncoded, Boolean doResidentGlyphs,
  404.                                                                     TfdbInfoFlags fdbFlags, OSErr *status)
  405.     {
  406.         long                            glyphCount;                        // Counter for printer font glyphs.
  407.         unsigned long            mask;                                    // Bit testing mask.
  408.         unsigned long            *nextResLong;                    // Long o'bits for traversing resident glyph bits.
  409.         unsigned long            *nextDocumentLong;        // Long o'bits for traversing document glyph bits.
  410.         unsigned long            *nextUsageLong;                // Long o'bits to mark glyph usage.
  411.         Boolean                        needMoreFonts=false;    // Do we need more fonts for this resident/doc font combo?
  412.         long                            num = 0;
  413.         long                            addGlyph;                            // Add this glyph to the encoding?
  414.         Boolean                        compositeFont;                // Are we working with a composite font on the printer?
  415.         
  416.         *status = noErr;
  417.  
  418.         compositeFont = (fontLocation->platform != gxGlyphPlatform) ? true : false;
  419.         if (!doResidentGlyphs)
  420.             compositeFont = false;            // downloaded fonts are never composite fonts to start out with. (Can become later)
  421.             
  422.         /******** Point into bit arrays for first glyph being asked for ***************/
  423.         
  424.         mask = 0x80000000U >> (*start & 0x0000001F);        // Initialize mask: start MOD 32 bit set.
  425.         {
  426.             long    bitArrayOffset = *start >> 5;                    // Get start DIV 32.
  427.                         
  428.             nextResLong = fontLocation->glyphBits + bitArrayOffset;                    // point into bit arrays.
  429.             nextUsageLong = printerFont->glyphUsage + bitArrayOffset;
  430.             nextDocumentLong = docGlyphBits + bitArrayOffset;
  431.                         
  432.         }
  433.         
  434.         if ( !compositeFont && (fdbFlags & fdbUseMac8Bit) ) {
  435.         
  436.             /*** If we are supposed to use standard mac 8 bit encoding ***/        
  437.         
  438.             unsigned short            *aGlyphCode;
  439.             
  440.             /** if we are encoding for resident font, make sure there are resident glyphs **/
  441.             
  442.             if (!doResidentGlyphs || CountGlyphBits(fontLocation->glyphBits, numGlyphs)) {
  443.             
  444.                 num = MakeMac8BitEncoding(printerFont->theRealFont, printerFont->printerFontCodes);
  445.                 check(num == 256);
  446.                 
  447.                 /** Set all bits in glyph usage array for this encoding **/
  448.                 aGlyphCode = printerFont->printerFontCodes;
  449.                 for (glyphCount = 0; glyphCount < 256; ++glyphCount) {
  450.                 
  451.                     if (*aGlyphCode <= numGlyphs) {
  452.                     
  453.                         BITSET(nextUsageLong, *aGlyphCode);
  454.                         
  455.                     } else {
  456.                     
  457.                         #if DEBUGLEVEL > 1
  458.                         dprintf(trace, "asked to encode glyph: %d, outside of font's range of %d", *aGlyphCode, numGlyphs);
  459.                         #endif
  460.                         
  461.                     }//end if
  462.                     
  463.                     ++aGlyphCode;
  464.                 
  465.                 }//end for
  466.                                                 
  467.             } else {
  468.             
  469.                 /*****
  470.                     We couldn't encode any glyphs because we were asked for resident
  471.                     encoding but the font needs to be downloaded
  472.                 *****/
  473.                 num = 0;        
  474.                 
  475.             }//end if
  476.         
  477.         } else {
  478.         
  479.             /****
  480.                 Make hash table encoding:
  481.                 Encode as many glyphs as we can from starting glyph through end.
  482.                 Stop when all glyphs have been encoded or hash table is full.
  483.             *****/
  484.             
  485.             /* resereve SEAC positions if necessary */
  486.             if (!compositeFont)
  487.                 FHMarkSEACPositions(printerFont->theRealFont, printerFont->printerFontCodes,  true );
  488.             
  489.             for (glyphCount = *start; glyphCount < numGlyphs; ++glyphCount) {
  490.             
  491.                 if (doResidentGlyphs)
  492.                     /** If printer font contains this glyph and doc requires it, encode it. **/
  493.                     addGlyph = (mask & *nextResLong & *nextDocumentLong);
  494.                 else
  495.                     /** If doc requires this glyph, and it is not a resident glyph encoded it. **/
  496.                     addGlyph = (mask & *nextDocumentLong & (~*nextResLong));
  497.     
  498.                 if (addGlyph) {
  499.                 
  500.                     /** If it is a composite font or we had room in the encoding, add it to the printer font **/
  501.                     if (compositeFont || FHAddGlyphHash(glyphCount, printerFont->printerFontCodes)) {
  502.  
  503.                         *nextUsageLong |= mask;            // Set the usage bit for this printer font.
  504.                         ++num;
  505.                         
  506.                     } else {            /*** There wasn't room for more glyphs, return that we need more fonts ***/
  507.                     
  508.                         *start = glyphCount;                // update starting glyph for next time.
  509.                         needMoreFonts = true;
  510.                         break;                                            // break out.
  511.                         
  512.                     }//end if
  513.                     
  514.                 }//end if
  515.             
  516.                 /** Advance the mask and pointer **/        
  517.                 if ( !(mask >>= 1) ) {
  518.                 
  519.                     mask = 0x80000000;
  520.         
  521.                     ++nextResLong;
  522.                     ++nextUsageLong;
  523.                     ++nextDocumentLong;
  524.                     
  525.                 }//end if
  526.                 
  527.             }//end for
  528.  
  529.             /* Unmark reserved SEAC positions */
  530.             if (!compositeFont)
  531.                 FHMarkSEACPositions(printerFont->theRealFont, printerFont->printerFontCodes, false );
  532.             
  533.         }//end if
  534.  
  535.         /** Make the glyph to character map if necessary **/
  536.         if (compositeFont && (num > 0)) {
  537.         
  538.             printerFont->info |= fontCantBeRencoded;
  539.             *status = FHMakeGlyphToCharMap(printerFont);
  540.             nrequire(*status, failed_glyphToChar);
  541.             
  542.         }//end if
  543.                     
  544.         *numEncoded = num;
  545.  
  546. failed_glyphToChar:        
  547.         return(needMoreFonts);
  548.     
  549.     }//FHMakePrinterGlyphEncoding
  550.  
  551.  
  552.  
  553. //<FF>
  554. /********************************************
  555.     
  556.     Function FHNewPrinterFont:
  557.     
  558.     Function grows the FHRec handle to hold another
  559.     printer font record, and returns a pointer to that
  560.     record.
  561.     
  562.     hFHRec:                        The font handler context handle.
  563.     theFont:                    The snapshot font reference for this printer font.
  564.     printerFontIndex:    The index of this printer font.
  565.     usageSize:                how many bytes for the glyph usage array (long alligned)
  566.     printerFont:            returned:  Pointer into the hFHRec for this printer font entry.
  567.     offset:                        returned:     Offset into record for this printer font entry.
  568.     
  569. **********************************************/
  570. OSErr FHNewPrinterFont(TFontHandlerHdl hFHRec, fhFont theFont, long printerFontIndex, long usageSize, TPrinterFontRec* *printerFont, long *offset);
  571. OSErr FHNewPrinterFont(TFontHandlerHdl hFHRec, fhFont theFont, long printerFontIndex, long usageSize, TPrinterFontRec* *printerFont, long *offset)
  572.     {
  573.         OSErr                                status;
  574.         long                                size, oldSize;
  575.         TFontHandlerPtr            pFHRec;
  576.         long                                nameLen;
  577.         long                                index;
  578.         gxFont                            theRealFont;
  579.         long                                dbIndex;
  580.         TPrinterFontRec            *thePrinterFont;
  581.  
  582.         theRealFont = FHGetSnapShotFont(hFHRec, theFont, &dbIndex);
  583.         check(theRealFont);
  584.         
  585.         /* Grow the font handler record */
  586.  
  587.         oldSize = sizeof(TFontHandlerRec) + (*hFHRec)->nextOffset;
  588.         size = sizeof(TPrinterFontRec) + usageSize;            
  589.         nrequire(status = PrSetHandleSize((Handle)hFHRec, oldSize + size), failed_SetSize);
  590.         
  591.         pFHRec = *hFHRec;
  592.         thePrinterFont = (TPrinterFontRec*)(pFHRec->printerFonts + pFHRec->nextOffset);
  593.         *offset = pFHRec->nextOffset;
  594.         pFHRec->nextOffset += size;
  595.         
  596.         
  597.         thePrinterFont->usageSize = usageSize;
  598.         thePrinterFont->nameIndex = kNoSuchFontName;                // no cache on font name index yet.
  599.         thePrinterFont->info = fontNotAvailable;                        // unknown information.
  600.         
  601.         /** Cache the font reference and index even though they are the tag and ID in the collection **/
  602.         
  603.         thePrinterFont->theFont = theFont;                                    // Cache the snapshot font reference in here.
  604.         thePrinterFont->prFontIndex = printerFontIndex;            // Cache the index in here.
  605.         thePrinterFont->theRealFont = theRealFont;                    // Cache the actual gx font reference here.
  606.         thePrinterFont->dbIndex = dbIndex;                                    // Cache this here, it helps us make names later.
  607.         
  608.         /***
  609.             Cache the index of the PostScript name:
  610.                 If we find a name, cache the index, 
  611.             else index will remain -1 as initialized
  612.         ***/
  613.  
  614.         nameLen = GXFindFontName(theRealFont, gxPostscriptFontName, gxMacintoshPlatform, gxNoScript, gxNoLanguage, nil, &index);
  615.         if (nameLen > 0)
  616.             thePrinterFont->nameIndex = index;
  617.         
  618.         /** Initialize printer codes to fhSentinalGlyphCode and glyph usage bits to 0 **/
  619.  
  620.         memset(thePrinterFont->glyphUsage, 0, usageSize);            // usageSize is size of glyph bits.
  621.         {
  622.             short idx;
  623.             unsigned short *p;
  624.             p = thePrinterFont->printerFontCodes;
  625.             for (idx = 255; idx >= -1; --idx)
  626.                 *p++ = fhSentinalGlyphCode;
  627.         }    
  628.         
  629.         thePrinterFont->glyphToCharCodeMap = nil;            // no handle for mapping glyphs to chars.
  630.         
  631.         *printerFont = thePrinterFont;
  632.  
  633. failed_SetSize:    
  634.             return(status);
  635.     
  636.     }//FHNewPrinterFont
  637.  
  638. //<FF>
  639. /************************************************
  640.  
  641.     Function:  FHAddPrinterFont.
  642.     
  643.     Function adds the required collection items for the
  644.     printer font.  Also increments the count of printer fonts.
  645.     
  646.     hFHRec:                font handler record handle.
  647.     theFont:            the font reference.
  648.     index:                Index of prnter font.
  649.     flags:                printer font flags.
  650.     offset:                Offset off of printerFonts field of font handler record.
  651.     
  652. **************************************************/
  653. OSErr FHAddPrinterFont(TFontHandlerHdl hFHRec, fhFont theFont, long index, long flags, long offset);
  654. OSErr FHAddPrinterFont(TFontHandlerHdl hFHRec, fhFont theFont, long index, long flags, long offset)
  655.     {
  656.         OSErr                    status;
  657.         
  658.         status = AddCollectionItem((*hFHRec)->printerFontsOffsets,
  659.                                                              (CollectionTag)theFont,
  660.                                                              index,
  661.                                                              4,
  662.                                                              &offset);
  663.         nrequire(status, failed_AddItem);
  664.         
  665.         status = SetCollectionItemInfo((*hFHRec)->printerFontsOffsets,
  666.                                                                      (CollectionTag)theFont,
  667.                                                                      index,
  668.                                                                     kCollectionUserAttributes,
  669.                                                                     flags);
  670.         nrequire(status, failed_AddItemInfo);
  671.         
  672.         (*hFHRec)->numPrFonts += 1;
  673.         
  674. failed_AddItemInfo:        
  675. failed_AddItem:
  676.  
  677.         return(status);
  678.     
  679.     }//FHAddPrinterFont
  680.  
  681. //<FF>
  682. /****************************************
  683.  
  684.     Function: FHAddPrinterFonts:
  685.     
  686.     Function takes a document font and adds
  687.     all required printer font entries to the list.
  688.     
  689.     hFHRec:            a font handler context handle.
  690.     theFont:        font ID of font to add printer fonts for.
  691.     glyphBits:    Pointer to the glyph bits for the document font.
  692.     nGlyphs:        number of total glyphs in document font.
  693.     fontFlags:    font flags from font database.
  694.     
  695. *****************************************/
  696. OSErr FHAddPrinterFonts(TFontHandlerHdl hFHRec, fhFont theFont, unsigned long *glyphBits, long nGlyphs, TfdbInfoFlags fdbFlags)
  697.     {
  698.         OSErr                                status;
  699.         long                                glyphsUsed;                                                    // Number of glyphs used in doc.
  700.         gxPrinterGlyphsRec    *fontLocation;                                            // A printer glyph location.
  701.         long                                glyphBitsSize;                                            // size of bit arrays.
  702.         long                                docFontFlags = 0;
  703.         gxFont                            theRealFont;                                                // The actual gx font reference for this fhFont.
  704.         TPrinterFontRec            *printerFont;                                                // A printer font record.
  705.         long                                startGlyph;                                                    // Glyph to start encoding a printer font at.
  706.         long                                offset, printerFontIndex;
  707.         Boolean                            needMoreFonts;                                            // Do we still need more printer fonts for the doc font?
  708.         Boolean                            canUse;                                                            // Can the font be downloaded?
  709.         long                                size;
  710.         long                                vmSize;                                                            // VM Size of the printer font.
  711.         long                                glyphsEncoded, totalGlyphsEncoded;
  712.         Handle                            workHandle;
  713.         long                                dbIndex;
  714.         
  715.         //dprintf(trace, "Adding printer fonts for font: %d", theFont);
  716.         
  717.         glyphsUsed = CountGlyphBits(glyphBits, nGlyphs);
  718.         
  719.         /** Initialize the font to be excluded from the prerequisite list **/
  720.         /**   A font only needs to be included if we are downloading it **/
  721.         
  722.         theRealFont = FHGetSnapShotFont(hFHRec, theFont, nil);
  723.         status = FontDbaseExcludePrerequisite((*hFHRec)->docDbase, theRealFont, true);
  724.         nrequire(status, failed_exclude);
  725.         
  726.         /******* Get printer information for this font ******/
  727.         
  728.         /** First make sure workspace is big enough **/
  729.         
  730.         glyphBitsSize =  4 * ( ( nGlyphs + 31 ) / 32 );
  731.         size = sizeof(gxPrinterGlyphsRec) - sizeof (unsigned long) + glyphBitsSize;
  732.         status = FHSetWorkHandleSize(hFHRec, size, 0, &workHandle);
  733.         nrequire(status, failed_SetSize);
  734.                     
  735.         HLock(workHandle);
  736.         fontLocation = (gxPrinterGlyphsRec*)*workHandle;
  737.         memset(fontLocation, 0, size);                                                                        // clear it so message can set bits for glyph usage.
  738.         fontLocation->theFont = FHGetSnapShotFont(hFHRec, theFont, &dbIndex);
  739.         fontLocation->nGlyphs = nGlyphs;
  740.  
  741.         /** Get the printer info for the font **/                        
  742.         
  743.         status = (*hFHRec)->psDevice->GetPrinterGlyphsInformation(fontLocation);        // DL 7/27/97:  Used to use GX message, now device method.
  744.         nrequire(status, failed_GetFontGlyphs);
  745.         
  746.  
  747.         /*** Build the entries for the printer resident glyphs ***/
  748.  
  749.         startGlyph = 0;
  750.         totalGlyphsEncoded = 0;
  751.         needMoreFonts = true;
  752.         
  753.         /**********
  754.             Find the index to start at for building printer fonts:
  755.             If there are currently no entries for the given font then
  756.             start at zero (this will be the case at doc-setup, but not
  757.             necessarily the case for fonts added during imaging time.
  758.             
  759.             The starting index is the number of printer fonts so far
  760.             since the indecies are zero-based.
  761.         **********/
  762.         printerFontIndex = CountTaggedCollectionItems((*hFHRec)->printerFontsOffsets, (CollectionTag)theFont);
  763.         
  764.         /*****************************
  765.         
  766.             Loop makes printer font records of up to 256 (except for printer resident composite fonts)
  767.             glyphs per record for all of the glyphs that
  768.             are contained in the resident font and required
  769.             by the document.
  770.             
  771.             Loop terminates when the whole document glyph
  772.             set is consumed by printer font records.
  773.             
  774.         ******************************/
  775.         
  776.         while (needMoreFonts) {            /** Do while we still need another printer font **/
  777.         
  778.             /** Make printer font record for next set of glyphs **/
  779.  
  780.             status = FHNewPrinterFont(hFHRec, theFont, printerFontIndex, glyphBitsSize, &printerFont, &offset);        // Warning, if memory moves printerFont invalidates.
  781.             nrequire(status, failed_NewPrinterFont);
  782.  
  783.             printerFont->docVMUsage = 0;                                            // Nothing to download.
  784.             printerFont->vmUsage = kEncodingOverhead;                    // memory used is just for encoding.
  785.             printerFont->usageSize = glyphBitsSize;
  786.         
  787.             /** Generate the encoding **/
  788.  
  789.             HLockHi((Handle)hFHRec);                // we don't want printerFont to move
  790.             printerFont = (TPrinterFontRec*)((*hFHRec)->printerFonts + offset);  // Point to it again.
  791.  
  792.             needMoreFonts = FHMakePrinterGlyphEncoding(nGlyphs, glyphBits, printerFont, fontLocation, 
  793.                                                                                     &startGlyph, &glyphsEncoded, true, fdbFlags, &status);
  794.             nrequire(status, failed_MakeEncoding);
  795.  
  796.             HUnlock((Handle)hFHRec);
  797.             
  798.             /** Add the collection item for this printer font **/
  799.             
  800.             if (glyphsEncoded > 0) {
  801.             
  802.                 printerFont->info |= fontIsInPrinter;            // We encoded some glyphs, mark as resident.
  803.                 
  804.                 status = FHAddPrinterFont(hFHRec, theFont, printerFontIndex, docFontFlags, offset);
  805.                 nrequire(status, failed_AddPrinterFont);
  806.                 
  807.                 /** printerFont is now invalid pointer because FHAddPrinterFont could move memory **/
  808.                 
  809.                 ++printerFontIndex;
  810.                 
  811.                 totalGlyphsEncoded += glyphsEncoded;
  812.                 
  813.             }//end if
  814.         
  815.         }//end while;
  816.         
  817.         /************************************************
  818.             Given the number of glyphs required by the document
  819.             that are printer resident and the rest of our global
  820.             information (such as printer type) see if it makes
  821.             sense to go ahead and do font downloading, or mark
  822.             the fontCantBeUsed flag on the printer font for all
  823.             glyphs.
  824.         *************************************************/
  825.         status = FHTestFontCanBeUsed(hFHRec, theFont, glyphsUsed, glyphsEncoded, &canUse);
  826.         nrequire(status, failed_testFont);
  827.         if ( !canUse ) {
  828.                     
  829.             printerFont = (TPrinterFontRec*)((*hFHRec)->printerFonts + offset);            // repoint to record in cased mem moved.
  830.             printerFont->info |= fontCantBeUsed;
  831.             printerFont->usageSize = 0;
  832.             
  833.             /***** 
  834.                 Set total encoded to be number of glyphs in font, 
  835.                 this will ensure that we don't try to encode any of
  836.                 these glyphs for downloading to the printer. Also,
  837.                 set all of the glyph bits in this printer font record
  838.                 so we always get a hit without searching.
  839.             *****/
  840.             totalGlyphsEncoded = glyphsUsed;
  841.             memset(printerFont->glyphUsage, 0xFF, glyphBitsSize);
  842.             
  843.             /** Add collection item for this font **/
  844.             status = FHAddPrinterFont(hFHRec, theFont, printerFontIndex, docFontFlags, offset);
  845.             nrequire(status, failed_AddPrinterFont);
  846.         
  847.         }//end if
  848.         
  849.         /************************************************
  850.             If there were any glyphs required by the document
  851.             that are not in the printer, make downloaded printer
  852.             fonts for them.  Code is mostly same as above.
  853.             Except that glyphs are guarenteed to be encoded
  854.             because there is no dependancy on printer resident glyphs.
  855.         *************************************************/
  856.         
  857.         if ( glyphsUsed > totalGlyphsEncoded) {
  858.         
  859.             /** If we are creating a font for downloading, make sure it is included for prerequisites **/
  860.             
  861.             status = FontDbaseExcludePrerequisite((*hFHRec)->docDbase, theRealFont, false);
  862.             nrequire(status, failed_excludeFalse);
  863.                     
  864.             /**********
  865.                 Compute the size of the document font excluding any glyphs already in the printer
  866.                 Note, this function uses workHandle[1] so make sure it is not in use during this call.
  867.                 Also, this call will move memory.
  868.             **********/
  869.             
  870.             status = FHComputeDocFontSize(hFHRec, theFont, nGlyphs, glyphBits, fontLocation->glyphBits, &vmSize);
  871.             nrequire(status, failed_ComputeSize);
  872.  
  873.             /** encode the rest of the glyphs **/
  874.             
  875.             needMoreFonts = true;
  876.             startGlyph = 0;
  877.             while (needMoreFonts) {            /** Do while we still need another printer font **/
  878.  
  879.                 /**********
  880.                     Only allocate a new printer font record if the one allocated for resident glyphs was
  881.                     used (some of the glyphs needed by doc are resident on printer).  If not, then the
  882.                     one allocated above is empty and we can use it.
  883.                 ***********/
  884.                 if (totalGlyphsEncoded > 0) {
  885.     
  886.                     status = FHNewPrinterFont(hFHRec, theFont, printerFontIndex, glyphBitsSize, &printerFont, &offset);        // Warning, if memory moves printerFont invalidates.
  887.                     nrequire(status, failed_NewPrinterFont);
  888.                     
  889.                 } else {
  890.                 
  891.                     /** Just use the printer font that was allocated before but recalculate pointer in case memory moved **/
  892.                     printerFont = (TPrinterFontRec*)((*hFHRec)->printerFonts + offset);
  893.                 
  894.                 }//end if
  895.                     
  896.                 printerFont->usageSize = glyphBitsSize;                        // size of the bit array.
  897.             
  898.                 /** Make printer font record for next set of glyphs **/
  899.                 
  900.                 HLockHi((Handle)hFHRec);                // we don't want printerFont to move
  901.                 printerFont = (TPrinterFontRec*)((*hFHRec)->printerFonts + offset);
  902.                 
  903.                 needMoreFonts = FHMakePrinterGlyphEncoding(nGlyphs, glyphBits, printerFont, fontLocation,
  904.                                                                             &startGlyph, &glyphsEncoded, false, fdbFlags, &status);
  905.                                                                             
  906.                 nrequire(status, failed_MakeEncoding);
  907.                 HUnlock((Handle)hFHRec);
  908.                                 
  909.                 if (glyphsEncoded > 0) {
  910.  
  911.                     totalGlyphsEncoded += glyphsEncoded;
  912.                     
  913.                     /** Compute the vm usage of this printer font **/
  914.  
  915.                     HLockHi((Handle)hFHRec);                // lock it down and re-point to the printer font record.
  916.                     printerFont = (TPrinterFontRec*)((*hFHRec)->printerFonts + offset);
  917.                     
  918.                     /** Compute the sizes for this printer font **/
  919.                     printerFont->docVMUsage = vmSize;                                                    // size of font for all document glyphs
  920.                     status = FHComputePrinterFontSize(hFHRec, printerFont);        // Size for just these glyphs.
  921.                     nrequire(status, failed_ComputePrSize);
  922.                     
  923.                     HUnlock((Handle)hFHRec);            // unlock it in for allocation of new printer fonts.
  924.  
  925.                     /** Add the collection item for this printer font **/
  926.                                     
  927.                     status = FHAddPrinterFont(hFHRec, theFont, printerFontIndex, docFontFlags, offset);
  928.                     nrequire(status, failed_AddPrinterFont);
  929.                     
  930.                     ++printerFontIndex;
  931.  
  932.                 }//end if
  933.                 
  934. #if DEBUGLEVEL > 1
  935.                 if (glyphsEncoded == 0) {
  936.                     status = -9999;
  937.                     DebugStr("\pSomehow no glyphs were encoded in downloadable font - This is a bug");
  938.                     goto failed_AddPrinterFont;
  939.                 }//end if
  940. #endif
  941.         
  942.             }//end while    
  943.         
  944.         }//end if
  945.                     
  946. failed_ComputePrSize:    
  947. failed_ComputeSize:        
  948. failed_excludeFalse:
  949. failed_testFont:
  950. failed_AddPrinterFont:
  951. failed_MakeEncoding:
  952. failed_NewPrinterFont:        
  953. failed_GetFontGlyphs:
  954.  
  955.      FHReleaseWorkspace(hFHRec, 0);
  956.  
  957. failed_SetSize:
  958. failed_exclude:
  959.  
  960.         return(status);
  961.         
  962.     }//FHAddPrinterFonts
  963.